package cn.slahser.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Vector;

import cn.slahser.model.Action;
import cn.slahser.model.Message;
import cn.slahser.model.ReplyExt;
import cn.slahser.model.ShuoExt;
import cn.slahser.model.Reply;
import cn.slahser.model.Shuo;
import cn.slahser.model.User;
import cn.slahser.model.UserInfo;
import cn.slahser.service.ReplyService;
import cn.slahser.service.ShuoService;
import cn.slahser.service.UserInfoService;
import cn.slahser.service.UserService;
import cn.slahser.tools.DbHelper;
import cn.slahser.tools.ServerConfig;

//登录服务器
public class ServeServer extends Thread {
	// socket
	private Socket socket = null;
	// 准备连接池，第二个参数为什么用oops呢？循环池内资源时，直接向stream里通知
	private static HashMap<Integer, ObjectOutputStream> UserPool = new HashMap<Integer, ObjectOutputStream>();
	// private static Vector<OutputStream> pool=new Vector();
	// 用户登出用户从pool中移除
	private int userid = 0;
	// serversocket
	private static ServerSocket server = null;
	// 用户关闭死循环服务
	private static boolean b = true;
	private ObjectInputStream oin = null;
	private ObjectOutputStream oout = null;

	// 子线程：应答客户端请求
	public void run() {
		try {
			oin = new ObjectInputStream(socket.getInputStream());
			oout = new ObjectOutputStream(socket.getOutputStream());
			while (true) {
				Message message = (Message) oin.readObject();
				// 处理登陆
				if (message.getType().equalsIgnoreCase(Message.LOGIN)) {
					this.processLogin(message);
					// 处理登出
				} else if (message.getType().equalsIgnoreCase(Message.LOGOUT)) {
					UserPool.remove(userid);
					throw new Exception();
					// 处理下载信息
				} else if (message.getType().equalsIgnoreCase(Message.DL_DATA)) {
					this.processDlData(message);
					// 处理发送信息
				} else if (message.getType()
						.equalsIgnoreCase(Message.SEND_TEXT)
						|| message.getType().equalsIgnoreCase(
								Message.SEND_IMAGE)
						|| message.getType().equalsIgnoreCase(Message.SEND_AMR)) {
					this.processSend(message);
					// 处理回复信息
				} else if (message.getType().equalsIgnoreCase(
						Message.REPLY_TEXT)
						|| message.getType().equalsIgnoreCase(
								Message.REPLY_IMAGE)
						|| message.getType()
								.equalsIgnoreCase(Message.REPLY_AMR)) {
					this.processReply(message);
					// 处理注册
				} else if (message.getType().equalsIgnoreCase(Message.REG)) {
					this.processReg(message);
				}
			}
		} catch (Exception e) {
			try {
				socket.close();
			} catch (Exception e1) {
			}
		}

	}

	public void processLogin(Message message) {
		try {
			int userid = Integer.parseInt(message.getValue().get("userid")
					.toString());
			String password = message.getValue().get("password").toString();
			Connection conn = DbHelper.getDb().getConn();
			UserService db = new UserService(conn);
			// 这个返回vector也没啥办法，
			Vector<User> findResult = db.findKey(userid);
			Message tempMsg = new Message();
			// 手动拿下第一个
			// findKey没找到结果
			if (findResult.size() >= 1) {
				// 判断密码结果
				if (findResult.get(0).getPassword().equalsIgnoreCase(password)) {
					// 判断登陆状态结果
					if (findResult.get(0).getState() == 1) {
						Hashtable<String, Object> table = new Hashtable<String, Object>();
						table.put("message", "ok");
						tempMsg.setReturnValue(table);
						// 值传进来
						this.userid = userid;
						// 抢线情况
						ObjectOutputStream tempOutStream = UserPool.get(userid);
						if (tempOutStream != null) {
							try {
								tempOutStream.close();
								UserPool.remove(userid);
							} catch (Exception ex) {
							}
						}
						UserPool.put(userid, oout);
						// 判断登陆状态结果
					} else {
						Hashtable<String, Object> table = new Hashtable<String, Object>();
						table.put("message", "error");
						tempMsg.setReturnValue(table);
					}
					// 判断密码错误
				} else {
					Hashtable<String, Object> table = new Hashtable<String, Object>();
					table.put("message", "psswordError");
					tempMsg.setReturnValue(table);
				}
				// findKey没找到结果
			} else {
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "noneUser");
				tempMsg.setReturnValue(table);
			}
			oout.writeObject(tempMsg);
			oout.flush();
			conn.close();

			if (!tempMsg.getReturnValue().get("message").equals("ok")) {
				throw new Exception();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void processDlData(Message message) {
		try {
			Connection conn = DbHelper.getDb().getConn();
			Message m1 = new Message();
			try {
				// 得到说说内容
				// 加一个列进来，左join，机智的连接查询，查询前10个
				ResultSet rs = conn.createStatement().executeQuery(
						"select top 10" + " t.titleid," + "t.userid,"
								+ "u.uname," + "t.titletext," + "t.type,"
								+ "t.sendcreate " + "from title "
								+ "t left join userinfo"
								+ " u on t.userid=u.userid"
								+ " order by t.sendcreate desc");
				Vector<ShuoExt> ti = new Vector<ShuoExt>();
				while (rs.next()) {
					// 说说必要的属性，生成一个对象
					ShuoExt in = new ShuoExt();
					in.setTitleid(rs.getString("titleid"));
					in.setSendcreate(rs.getString("sendcreate"));
					in.setType(rs.getString("type"));
					in.setUname(rs.getString("uname"));
					in.setUserid(rs.getString("userid"));
					in.setTitletxt(rs.getString("titletxt"));
					// 添加进入集合
					ti.add(in);

					// 得到该说说回复内容，拼接一条sql出来
					ResultSet rs1 = conn
							.createStatement()
							.executeQuery(
									"select h.reid"
											+ ",h.text,h.type,h.sendtime,h.userid,u.uname,h.titleid from reply h inner join userinfo u "
											+ "on h.userid=u.userid and"
											+ " h.titleid=" + in.getTitleid()
											+ " order by h.sendtime");
					// 上面那句把titleid传进去，匹配具体的回复们
					while (rs1.next()) {
						ReplyExt h = new ReplyExt();
						h.setUserid(rs1.getString("userid"));
						h.setSendtime(rs1.getString("sendtime"));
						h.setTitleid(rs1.getString("titleid"));
						h.setText(rs1.getString("txt"));
						h.setType(rs1.getString("type"));
						h.setUname(rs1.getString("uname"));
						h.setReid(rs1.getString("hid"));
						in.getReplys().add(h);
					}
				}

				// 生成返回信息
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "ok");
				table.put("infos", ti);
				System.out.println(ti.size() + "------------");
				// 设置返回值
				m1.setReturnValue(table);
			} catch (Exception e) {
				e.printStackTrace();
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "error");
				m1.setReturnValue(table);
			} finally {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			try {
				oout.writeObject(m1);
				oout.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}

	}

	public void processSend(Message message) {
		try {
			Message tempMsg = new Message();
			Connection conn = DbHelper.getDb().getConn();
			// 向title表里添信息也就是发说说
			try {
				Shuo t = new Shuo();
				t.setUserid(Integer.parseInt(message.getValue().get("userid")
						.toString()));
				t.setTitletxt(message.getValue().get("text").toString());
				t.setType(message.getType());
				// 赶紧把说说存起来
				new ShuoService(conn).add(t);
				// 关闭连接
				conn.close();

				// 构造返回信息
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "ok");
				tempMsg.setReturnValue(table);

				// 解决并发问题，并且进行通知，不提示数目，说有更新
				Message m2 = new Message();
				Hashtable<String, Object> table1 = new Hashtable<String, Object>();
				table1.put("message", "action");
				m2.setReturnValue(table1);

				// 需要通知大家更新
				new Action(m2).start();
			} catch (Exception e) {
				// 构造返回信息
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "error");
				tempMsg.setReturnValue(table);
			} finally {
				try {
					conn.close();
				} catch (Exception e2) {
				}
			}
			// 设置返回信息
			oout.writeObject(tempMsg);
			// 阻塞
			oout.flush();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	public void processReg(Message message) {
		try {
			Connection conn = DbHelper.getDb().getConn();
			Message tempMsg = new Message();
			try {
				// 设置手动事务
				conn.setAutoCommit(false);
				UserService db = new UserService(conn);
				User tempUser = new User();
				tempUser.setPassword(message.getValue().get("password")
						.toString());
				// 第一次状态
				tempUser.setState(0);

				// 随机生成key用来交换数据
				String key = new Date().getTime() + "R"
						+ (Math.random() * 1000) + "R" + (Math.random() * 1000);
				tempUser.setUkey(key);
				// 添加
				db.add(tempUser);

				// 查询出拥有这把key的对象，同时设置手动事务
				Vector<User> v = db.findColumnName(UserService.UKEY, key);
				// 取出第一个
				tempUser = v.get(0);

				// 构造对象
				UserInfo userInfo = new UserInfo();
				// 交互点！
				userInfo.setUserid(tempUser.getUserid());
				userInfo.setUname(message.getValue().get("uname").toString());
				userInfo.setAddress(message.getValue().get("address")
						.toString());
				userInfo.setPhone(message.getValue().get("phone").toString());
				userInfo.setSex(message.getValue().get("sex").toString());
				// 将userinfo入库并提交
				new UserInfoService(conn).add(userInfo);
				conn.commit();

				// 设置返回信息table
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "ok");
				// 这里添userinfo也ok
				table.put("userid", tempUser.getUserid() + "");
				table.put("uname", userInfo.getUname());
				tempMsg.setReturnValue(table);

			} catch (Exception e) {
				// 出现异常则回滚
				conn.rollback();
				// 设置返回信息
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "error");
				tempMsg.setReturnValue(table);
			} finally {
				conn.close();
			}
			// 填充设置返回信息
			oout.writeObject(tempMsg);
			oout.close();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	/***
	 * 回复 跟send差不多，不做更多注释了
	 * 
	 * @param message
	 */
	public void processReply(Message message) {
		try {
			Message m1 = new Message();
			Connection conn = DbHelper.getDb().getConn();
			try {
				// 存储回复对象信息
				Reply t = new Reply();
				t.setUserid(Integer.parseInt(message.getValue().get("userid")
						.toString()));
				t.setTitleid(Integer.parseInt(message.getValue().get("titleid")
						.toString()));
				t.setType(message.getType());
				t.setText(message.getValue().get("text").toString());
				new ReplyService(conn).add(t);
				conn.close();

				// 构造返回信息
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "ok");
				m1.setReturnValue(table);

				// 处理兵法，并且进行通知更新
				Message m2 = new Message();
				Hashtable<String, Object> table1 = new Hashtable<String, Object>();
				table1.put("message", "action");
				m2.setReturnValue(table1);
				// 需要通知大家更新
				new Action(m2).start();

			} catch (Exception e) {
				Hashtable<String, Object> table = new Hashtable<String, Object>();
				table.put("message", "error");
				m1.setReturnValue(table);
			} finally {
				try {
					conn.close();
				} catch (Exception e2) {
				}
			}
			oout.writeObject(m1);
			oout.flush();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	public static void openServer() throws Exception {
		try {
			server = new ServerSocket(Integer.parseInt(ServerConfig
					.getValue("server_port")));
			// 做一个死循环一直接收请求
			while (b) {
				// 返回值是socket
				new ServeServer(server.accept()).start();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			try {
				server.close();
			} catch (Exception e) {
			}
			throw ex;
		}
	}

	public static void closeServer() throws Exception {
		try {
			b = false;
			server.close();
		} catch (Exception ex) {
			throw ex;
		}
	}

	public ServeServer(Socket socket) {
		this.socket = socket;
	}
}
